<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta http-equiv="Content-Style-Type" content="text/css">
<link rel="up" title="FatFs" href="../00index_e.html">
<link rel="stylesheet" href="../css_e.css" type="text/css" media="screen" title="ELM Default">
<title>FatFs Module Application Note</title>
</head>

<body>
<h1>FatFs Module Application Note</h1>
<hr>

<div class="para">
<h3>Considerations on porting to various platform</h3>
<p>The FatFs module is assuming following terms on portability.</p>
<ul>
<li>ANSI C<br>
The FatFs module is a middleware that written in ANSI C. There is no platform dependence, so long as the compiler is in compliance with ANSI C.</li>
<li>Size of integer types<br>
The FatFs module assumes that size of char/short/long are 8/16/32-bit and int is 16 or 32 bit. These correspondence are defined in integer.h. This will not be a problem on most compilers. When any conflict with existing definitions is occured, you must resolve it with care.</li>
</ul>
</div>

<div class="para">
<h3>Memory Usage (R0.07e)</h3>
<table class="lst2">
<tr><th></th><th>AVR</th><th>H8/300H</th><th>PIC</th><th>TLCS-870/C</th><th>V850ES</th><th>SH2</th><th>ARM7TDMI</th><th>x86</th></tr>
<tr><td>Compiler</td><td>WinAVR(gcc)</td><td>CH38</td><td>C30(gcc)</td><td>CC870C</td><td>CA850</td><td>SHC</td><td>WinARM(gcc)</td><td>VC6</td></tr>
<tr><td>_WORD_ACCESS</td><td>1</td><td>0</td><td>0</td><td>1</td><td>1</td><td>0</td><td>0</td><td>1</td></tr>
<tr class="lst3"><td>text (Full, R/W)</td><td>12194</td><td>10559</td><td>10924</td><td>15229</td><td>7686</td><td>8727</td><td>10564</td><td>7342</td></tr>
<tr> <td>text (Min, R/W)</td><td>7988</td><td>6903</td><td>7108</td><td>9960</td><td>4884</td><td>5651</td><td>6544</td><td>4764</td></tr>
<tr><td>text (Full, R/O)</td><td>5532</td><td>4753</td><td>5020</td><td>6760</td><td>3462</td><td>3777</td><td>4624</td><td>3316</td></tr>
<tr> <td>text (Min, R/O)</td><td>4040</td><td>3631</td><td>3736</td><td>5083</td><td>2556</td><td>2907</td><td>3284</td><td>2510</td></tr>
<tr><td>bss</td><td>D*2 + 2</td><td>D*4 + 2</td><td>D*2 + 2</td><td>D*2 + 2</td><td>D*4 + 2</td><td>D*4 + 2</td><td>D*4 + 2</td><td>D*4 + 2</td></tr>
<tr><td>Work area<br>(_FS_TINY == 0)</td><td>D*560 +<br>F*544</td><td>D*560 +<br>F*550</td><td>D*560 +<br>F*544</td><td></td><td>D*560 +<br>F*550</td><td>D*560 +<br>F*550</td><td>D*560 +<br>F*550</td><td>D*560 +<br>F*550</td></tr>
<tr><td>Work area<br>(_FS_TINY == 1)</td><td>D*560 +<br>F*32</td><td>D*560 +<br>F*36</td><td>D*560 +<br>F*32</td><td>D*560 +<br>F*32</td><td>D*560 +<br>F*36</td><td>D*560 +<br>F*36</td><td>D*560 +<br>F*36</td><td>D*560 +<br>F*36</td></tr>
</table>
<p>These are the memory usage on some target systems with following condition. The memory sizes are in unit of byte, D means number of volumes and F means number of open files. All samples are optimezed in code size.</p>
<pre>
_FS_READONLY     0 (R/W), 1 (R/O)
_FS_MINIMIZE     0 (Full function), 3 (Minimized function)
_USE_STRFUNC     0 (Disable string functions)
_USE_MKFS        0 (Disable f_mkfs function)
_USE_FORWARD     0 (Disable f_forward function)
_CODE_PAGE       932 (Japanese Shift-JIS)
_USE_LFN         0 (Disable LFN)
_LFN_UNICODE     0 (Disable Unicode API)
_MAX_SS          512 (Single sector size)
_FS_RPATH        0 (Disable relative path)
_MULTI_PARTITION 0 (Single partition per drive)
_FS_REENTRANT    0 (Disable reentrancy)
</pre>
</div>

<div class="para">
<h3>Module Size Reduction</h3>
<p>Follwing table shows which function is removed by configuration options for the module size reduction.</p>
<table class="lst2">
<tr><td rowspan="2">Function</td><td colspan="3">_FS_MINIMIZE</td><td>_FS_READONLY</td><td>_USE_STRFUNC</td><td>_FS_RPATH</td><td>_USE_MKFS</td><td>_USE_FORWARD</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>1</td><td>0</td><td>0</td><td>0</td><td>0</td></tr>
<tr class="lst3"><td>f_mount</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>f_open</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>f_close</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>f_read</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>f_write</td><td></td><td></td><td></td><td>x</td><td></td><td></td><td></td><td></td></tr>
<tr><td>f_sync</td><td></td><td></td><td></td><td>x</td><td></td><td></td><td></td><td></td></tr>
<tr><td>f_lseek</td><td></td><td></td><td>x</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>f_opendir</td><td></td><td>x</td><td>x</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>f_readdir</td><td></td><td>x</td><td>x</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>f_stat</td><td>x</td><td>x</td><td>x</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>f_getfree</td><td>x</td><td>x</td><td>x</td><td>x</td><td></td><td></td><td></td><td></td></tr>
<tr><td>f_truncate</td><td>x</td><td>x</td><td>x</td><td>x</td><td></td><td></td><td></td><td></td></tr>
<tr><td>f_unlink</td><td>x</td><td>x</td><td>x</td><td>x</td><td></td><td></td><td></td><td></td></tr>
<tr><td>f_mkdir</td><td>x</td><td>x</td><td>x</td><td>x</td><td></td><td></td><td></td><td></td></tr>
<tr><td>f_chmod</td><td>x</td><td>x</td><td>x</td><td>x</td><td></td><td></td><td></td><td></td></tr>
<tr><td>f_utime</td><td>x</td><td>x</td><td>x</td><td>x</td><td></td><td></td><td></td><td></td></tr>
<tr><td>f_rename</td><td>x</td><td>x</td><td>x</td><td>x</td><td></td><td></td><td></td><td></td></tr>
<tr><td>f_chdir</td><td></td><td></td><td></td><td></td><td></td><td>x</td><td></td><td></td></tr>
<tr><td>f_chdrive</td><td></td><td></td><td></td><td></td><td></td><td>x</td><td></td><td></td></tr>
<tr><td>f_mkfs</td><td></td><td></td><td></td><td>x</td><td></td><td></td><td>x</td><td></td></tr>
<tr><td>f_forward</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td>x</td></tr>
<tr><td>f_putc</td><td></td><td></td><td></td><td>x</td><td>x</td><td></td><td></td><td></td></tr>
<tr><td>f_puts</td><td></td><td></td><td></td><td>x</td><td>x</td><td></td><td></td><td></td></tr>
<tr><td>f_printf</td><td></td><td></td><td></td><td>x</td><td>x</td><td></td><td></td><td></td></tr>
<tr><td>f_gets</td><td></td><td></td><td></td><td></td><td>x</td><td></td><td></td><td></td></tr>
</table>
</div>

<div class="para">
<h3>Long File Name</h3>
<p>The FatFs module supports long file name (LFN) from revision 0.07. The two different file names, SFN and LFN, of a file is transparent in the file functions except for f_readdir function. To enable LFN feature, set <tt>_USE_LFN</tt> to 1 or 2, and add a Unicode code conversion function ff_convert and ff_wtoupper to the project. This function is available in <tt>cc*.c</tt>. The LFN feature requiers a certain working buffer in addition. The buffer size can be configured by <tt>_MAX_LFN</tt> corresponding to the available memory size. The size of long file name will reach up to 255 characters so that the <tt>_MAX_LFN</tt> should be set to 255 for full featured LFN operation. When the size of working buffer is insufficient for the given file name, the file function will fail with <tt>FR_INVALID_NAME</tt>. When enable the LFN feature with re-entrant feature, <tt>_USE_LFN</tt> must be set to 2. In this case, the file funciton allocates the working buffer on the stack. The working buffer occupies <tt>(_MAX_LFN + 1) * 2</tt> bytes so that the caller's stack must be a sufficient size considering the working buffer.</p>
<table class="lst2 rset">
<caption>LFN cfg on ARM7</caption>
<tr><th>Code page</th><th>ROM size [bytes]</th></tr>
<tr><td>SBCS</td><td>+3721</td></tr>
<tr><td>932(Shift-JIS)</td><td>+62609</td></tr>
<tr><td>936(GBK)</td><td>+177797</td></tr>
<tr><td>949(Korean)</td><td>+139857</td></tr>
<tr><td>950(Big5)</td><td>+111497</td></tr>
</table>
<p>When the LFN feature is enabled, the module size will be increased depends on the selected code page. Right table shows the difference in module size when LFN is enabled with some code pages. We are the Japanese, Chinese and Korean have tens of thousands of characters. Unfortunately, it requires a huge OEM-Unicode bidirectional conversion table and the module size will be drastically increased that shown in the table. As the result, the FatFs with LFN will not able to be implemented to most 8-bit microcontrollers including AVR. <small>This is the reason why I had not been interested in implementing the LFN feature for a long time :-)</small></p>
<p>Note that the LFN feature on the FAT file system is a patent of Microsoft Corporation. When enable it on the commercial products, a license from Microsoft may be required depends on the final destination.</p>
</div>

<div class="para">
<h3>Re-entrancy</h3>
<p>The file operations to the different volume can always work simultaneously regardless of re-entrancy setting. The re-entrancy to the same volume can be enabled with <tt>_FS_REENTRANT</tt> option. In this case, also the OS dependent synchronization object control functions, ff_cre_syncobj, ff_del_syncobj, ff_req_grant and ff_rel_grant must be added to the project. The sample code with documentation is available in <tt>syncobj.c</tt>.</p>
<p>When a file function is called while the volume is in use by any other task, the access is blocked until the task leaves file function. If wait time exceeded a period defined by <tt>_TIMEOUT</tt>, the file function will abort with <tt>FR_TIMEOUT</tt>. The timeout feature might not be supported on some RTOS.</p>
<p>There is an exception on f_mount and f_mkfs function. These functions are not re-entrant to the same volume. When use these functions, all other task must close the corresponding file on the volume and avoid to access the volume.</p>
<p>Note that this section describes on the re-entrancy of the FatFs module itself. There is no assumtion on the re-entrancy of low level disk I/O module.</p>
</div>

<div class="para">
<h3>Duplicated file access</h3>
<p>FatFs module does not support the shareing controls of duplicated file access. It is permitted when open method to the file is only read mode. The duplicated open in write mode to a file is always prohibited and open file must not be renamed, deleted, otherwise the FAT structure on the volume can be collapted.</p>
</div>

<div class="para">
<h3>Performance effective file access</h3>
<p>For good performance on reading/writing files on the small embedded system, application programmer should consider what process is done in the FatFs module. The file data on the disk is transferred in following sequence by f_read function.</p>
<p>Figure 1. Sector miss-aligned read (short)<br>
<img src="../img/f1.png" width="490" height="73" alt="">
</p>
<p>Figure 2. Sector miss-aligned read (long)<br>
<img src="../img/f2.png" width="490" height="140" alt="">
</p>
<p>Figure 3. Sector aligned read<br>
<img src="../img/f3.png" width="490" height="119" alt="">
</p>
<p>The file I/O buffer means a sector buffer to read/write a partial data on the sector. The sector buffer is either file private sector buffer on each file object or shared sector buffer on the file system object. The buffer configuration option <tt>_FS_TINY</tt> determins which sector buffer is used for the file data transfer. When tiny buffer (1) is selected, data memory consumption is reduced 512 bytes each file object. In this case, FatFs module uses only a sector buffer on the file system object for file data transfer and FAT/directory access. The disadvantage of the tiny buffer configuration is: the FAT data cached in the sector buffer will be lost by file data transfer and it must be reloaded at every cluster boundary. However it will be suitable for most application from view point of the decent performance and low memory comsumption.</p>
<p>Figure 1 shows that partial sector data is transferred via the file I/O buffer. On long data transfer shown in Figure 2, middle of transfer data that covers one or more sector is transferred to application buffer directly. Figure 3 shows that the case of entier transfer data is aligned to the sector boundary. In this case, file I/O buffer is not used. On the direct transfer, the maximum extent of sectors are read with disk_read function at a time but the multi sector transfer never across the cluster boundary even if it is contiguous.</p>
<p>Therefore taking effort to sector aligned read/write accesss avoids buffered data transfer and the read/write performance will be improved. Besides the effect, cached FAT data will not be flushed by file data transfer on the tiny configuration so that it can achieve same performance as non tiny configuration with small memory footprint.</p>
</div>

<div class="para">
<h3>Critical Section</h3>
<p>When write operation to the FAT file system is interrupted due to any accidental failure, such as sudden blackout, incorrect disk removal and unrecoverable disk error, the FAT structure can be collapted. Following images shows the critical section on the FatFs application.</p>
<div class="lset">
Figure 4. Long critical section<br>
<img src="../img/f4.png" width="320" height="436" alt="fig.4">
</div>
<div class="lset">
Figure 5. Minimized critical section<br>
<img src="../img/f5.png" width="320" height="436" alt="fig.5">
</div>
<br class="clr">
<p>An interruption in the red section can cause a cross link; as a result, the file/directory being changed may be lost. There is one or more possibility listed below when an interruption in the yellow section is occured.</p>
<ul>
<li>File data being rewrited is collapted.</li>
<li>A file being appended returns initial state.</li>
<li>A file created as new is gone.</li>
<li>A file created as new or in overwritten remains with length of zero.</li>
<li>Efficiency of disk use gets worse due to lost chain.</li>
</ul>
<p>Each case does not affect the files that not in write mode open. To minimize risk of data loss, the critical section can be minimized like shown in Figure 5 by minimizing the time that file is opened in write mode or using f_sync function properly.</p>
</div>

<div class="para">
<h3>Unicode API</h3>
<p>FatFs supports OEM code set on the API in default but FatFs can also switch the code set to Unicode. For more information, refer to the description in the <a href="filename.html">file name</a>.</p>
</div>


<div class="para">
<h3>About FatFs License</h3>
<p>This is a copy of the FatFs license document that included in the source codes.</p>
<pre>/*----------------------------------------------------------------------------/
/  FatFs - FAT file system module  R0.07e                    (C)ChaN, 2009
/-----------------------------------------------------------------------------/
/ FatFs module is a generic FAT file system module for small embedded systems.
/ This is a free software that opened for education, research and commercial
/ developments under license policy of following trems.
/
/  Copyright (C) 2009, ChaN, all right reserved.
/
/ * The FatFs module is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
/   personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
/ * Redistributions of source code must retain the above copyright notice.
/
/-----------------------------------------------------------------------------/</pre>
<p>Therefore FatFs license is one of the BSD-style license but there is a big difference. Because FatFs is for embedded projects, the conditions for redistributions in binary form, such as embedded code, hex file and binary library, are not specified to increase its usability. The documentation of the distributions need not include about FatFs and its license document, and it may also. Of course FatFs is compatible with the projects under GNU GPL. When redistribute it with any modification, the license can also be changed to GNU GPL or BSD license.</p>
</div>

<p class="foot"><a href="../00index_e.html">Return</a></p>
</body>
</html>
